In [1]:
import pandas as pd
from bokeh.plotting import show, output_notebook
output_notebook()
In [2]:
# You can see how this was made in the map_data.py under washmap/washmap
data = pd.read_hdf('static_map_data.hdf', 'df') # note we have to use hdf, not csv for the xs & ys lists
data.head()
Out[2]:
In [3]:
from bokeh.models import Plot, Range1d
from chart_constants import PLOT_FORMATS
x_range = Range1d(0, 250)
y_range = Range1d(0, 120)
text_box = Plot(
x_range=x_range, y_range=y_range, title="",
plot_width=250, plot_height=120, min_border=0,
**PLOT_FORMATS
)
In [4]:
from bokeh.models import Text, Rect, Triangle
from chart_constants import FONT_PROPS_SM, BLUE, ORANGE, ORANGE_SHADOW
text_box.add_glyph(
Text(x=95, y=20, text=['of people had'], **FONT_PROPS_SM)
)
text_box.add_glyph(
Text(x=95, y=5, text=['access in'], **FONT_PROPS_SM)
)
text_box.add_glyph(
Rect(x=75, y=55, width=200, height=5,
fill_color=BLUE, line_color=None)
)
text_box.add_glyph(
Triangle(x=150, y=65, size=25,
fill_color=ORANGE_SHADOW, line_color=None)
)
text_box.add_glyph(
Rect(x=200, y=60, width=100, height=40,
fill_color=ORANGE, line_color=None)
)
show(text_box)
In [5]:
def setup_map_plot():
x_start, x_end = (-20, 60)
y_start, y_end = (-40, 40)
aspect_ratio = (x_end - x_start) / (y_end - y_start)
x_range = Range1d(x_start, x_end)
y_range = Range1d(y_start, y_end)
plot_height = 400
return Plot(x_range=x_range, y_range=y_range, title="", plot_width=int(plot_height * aspect_ratio), plot_height=plot_height, **PLOT_FORMATS)
In [6]:
from bokeh.models import ColumnDataSource
source = ColumnDataSource(data)
data[['xs', 'ys', 'wat_color']].head(3)
Out[6]:
In [7]:
from bokeh.models import Patches
countries = Patches(
xs='xs',
ys='ys',
fill_color='wat_color',
line_color="#FFFFFF",
)
map_box = setup_map_plot()
map_box.add_glyph(ColumnDataSource(data), countries)
show(map_box)
In [8]:
from bokeh.models import TapTool
map_box = setup_map_plot()
map_box.add_glyph(ColumnDataSource(data), countries)
map_box.add_tools(TapTool())
show(map_box)
In [9]:
selected_countries = Patches(
xs='xs',
ys='ys',
fill_color='wat_color',
line_color=ORANGE,
line_width=5,
)
map_box = setup_map_plot()
map_box.add_glyph(ColumnDataSource(data), countries, selection_glyph=selected_countries, nonselection_glyph=countries)
map_box.add_tools(TapTool())
show(map_box)
In [10]:
from bokeh.models import HoverTool
map_box = setup_map_plot()
map_box.add_glyph(ColumnDataSource(data), countries, selection_glyph=selected_countries, nonselection_glyph=countries)
map_box.add_tools(TapTool())
map_box.add_tools(HoverTool(tooltips="@year<br />@name<br />@wat_value %"))
show(map_box)
In [28]:
def make_map(source, fill_color_string='wat_color', value_string='wat_value'):
countries = Patches(
xs='xs',
ys='ys',
fill_color=fill_color_string,
line_color="#FFFFFF",
)
selected_countries = Patches(
xs='xs',
ys='ys',
fill_color=fill_color_string,
line_color=ORANGE,
line_width=5,
)
map_box = setup_map_plot()
map_box.add_glyph(source, countries, selection_glyph=selected_countries, nonselection_glyph=countries)
map_box.add_tools(TapTool())
tooltips = "@year<br />@name<br />@" + value_string + " %"
map_box.add_tools(HoverTool(tooltips=tooltips))
return map_box
In [29]:
from bokeh.models import Text
from chart_constants import FONT_PROPS_SM, FONT_PROPS_MD, FONT_PROPS_LG
def construct_text_box(source, value_string, color_string, bar_color):
# Plot and axes
xdr = Range1d(0, 220)
ydr = Range1d(0, 120)
plot = Plot(
x_range=xdr,
y_range=ydr,
title="",
plot_width=250,
plot_height=120,
min_border=0,
**PLOT_FORMATS
)
# Add the writing
country = Text(x=5, y=50, text='name', **FONT_PROPS_MD)
percent = Text(x=15, y=10, text=value_string, text_color=color_string, **FONT_PROPS_LG) # nopep8
percent_sign = Text(x=69, y=10, text=['%'], text_color=color_string, **FONT_PROPS_LG) # nopep8
line_one = Text(x=90, y=28, text=['of people had'], **FONT_PROPS_SM)
line_two_p1 = Text(x=90, y=14, text=['access in'], **FONT_PROPS_SM)
line_two_p2 = Text(x=136, y=14, text='year', **FONT_PROPS_SM)
plot.add_glyph(source, Text(), selection_glyph=country)
plot.add_glyph(source, Text(), selection_glyph=percent)
plot.add_glyph(source, Text(), selection_glyph=percent_sign)
plot.add_glyph(line_one)
plot.add_glyph(line_two_p1)
plot.add_glyph(source, Text(), selection_glyph=line_two_p2)
# Add the orange box with year
shadow = Triangle(x=150, y=109, size=25, fill_color=ORANGE_SHADOW, line_color=None) # nopep8
plot.add_glyph(shadow)
# Add the blue bar
rect = Rect(x=75, y=99, width=150, height=5, fill_color=bar_color, line_color=None) # nopep8
plot.add_glyph(rect)
box = Rect(x=200, y=100, width=100, height=40, fill_color=ORANGE, line_color=None) # nopep8
plot.add_glyph(box)
year = Text(x=160, y=85, text='year', text_font_size='18pt', text_color="#FFFFF", text_font_style="bold") # nopep8
plot.add_glyph(source, Text(), selection_glyph=year)
return plot
show(construct_text_box(source, 'wat_value', 'wat_color', BLUE))
In [30]:
from bokeh.plotting import hplot, vplot
source = ColumnDataSource(data)
map_plot = make_map(source)
text_box = construct_text_box(source, 'wat_value', 'wat_color', BLUE)
show(hplot(vplot(map_plot), vplot(text_box)))
In [34]:
from bokeh.models.widgets import Tabs, Panel
from chart_constants import GREEN
# Select a country by default
source = ColumnDataSource(data)
source.selected = [30]
water_plot = make_map(source, 'wat_color', 'wat_value')
water_text = construct_text_box(source, 'wat_value', 'wat_color', BLUE)
sanitation_plot = make_map(source, 'san_color', 'san_value')
sanitation_text = construct_text_box(source, 'san_value', 'san_color', GREEN)
tabs = Tabs(tabs=[
Panel(title="Water", child=hplot(vplot(water_plot), vplot(water_text))),
Panel(title="Sanitation", child=hplot(vplot(sanitation_plot), vplot(sanitation_text)))
])
show(vplot(tabs))